package com.anti.modular.commonutils;

import cn.hutool.core.date.DateUtil;
import com.anti.commom.core.utils.DecimalUtils;
import com.anti.modular.bus.houselease.vo.DayCompare;
import com.anti.modular.bus.houselease.vo.TimeVo;
import com.anti.modular.commonutils.pojo.HasMonth;

import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * @Description 计算账单周期工具类
 * @Author anTi
 * @Date 2021-5-21
 */
public class CalculateQsbak {

    /**
     * 获取账单周期
     * @param rentStartDate
     * @param rentEndDate
     * @param receiptFu
     * @param receiptYj
     * @return
     */
    public static List<TimeVo> calculateQs(Date rentStartDate, Date rentEndDate, int receiptFu, int receiptYj){
        List<TimeVo> days=new ArrayList<>();
        // 计算设置
        if (1 == receiptYj){
            days = getDays(receiptFu, DateUtil.format(rentStartDate,"yyyy-MM-dd"), DateUtil.format(rentEndDate,"yyyy-MM-dd"));
        }else if (2 == receiptYj){
            days = getMonths(receiptFu,DateUtil.format(rentStartDate,"yyyy-MM-dd"), DateUtil.format(rentEndDate,"yyyy-MM-dd"));
        }else if (3 == receiptYj){
            days = getYears(receiptFu,DateUtil.format(rentStartDate,"yyyy-MM-dd"), DateUtil.format(rentEndDate,"yyyy-MM-dd"));
        }else {
            TimeVo timeVo=new TimeVo();
            timeVo.setStart(rentStartDate);
            timeVo.setEnd(rentEndDate);
            days.add(timeVo);
        }
        return days;
    }

    /**
     * 根据周期获取租金
     * @param amount  是否保留小数点 或者四舍五入取整
     * @param calculateStyle 每月周期计算
     * @param receiptFu
     * @param receiptYj
     * @param rentStartDate
     * @param rentEndDate
     * @param rent
     * @return
     */
    public static BigDecimal getRentMoney(int amount, int calculateStyle, int receiptFu, int receiptYj, Date rentStartDate, Date rentEndDate, BigDecimal rent) {
        DayCompare timeLength = getTimeLength(rentStartDate,rentEndDate, receiptYj);
        if (receiptYj == 1){
            int betweenDay = (int)DateUtil.betweenDay(rentStartDate, rentEndDate, true)+1;
            rent= DecimalUtils.multiple(rent,betweenDay);
        }else if (receiptYj ==2){
            //正常是1个月
            rent= getBigDecimalByMonths(calculateStyle, receiptFu, rent,DateUtil.format(rentStartDate,"yyyy-MM-dd"),DateUtil.format(rentEndDate,"yyyy-MM-dd"));
        }else if (receiptYj ==3){
            rent=  getBigDecimalByYears(calculateStyle, receiptFu, rent,DateUtil.format(rentStartDate,"yyyy-MM-dd"),DateUtil.format(rentEndDate,"yyyy-MM-dd"));
        }
        if (amount==0){
            //小数点后两位
            rent=DecimalUtils.scale(rent,2);
        }else {
            //四舍五入
            BigDecimal scale = DecimalUtils.scale(rent,2);
            long l  = scale.setScale( 0, BigDecimal.ROUND_HALF_UP ).longValue(); // 四舍五入
            rent = DecimalUtils.toBigDecimal(l);
        }
        return rent;
    }

    public static List<TimeVo> getDays(int num,String startTime, String endTime) {
        // 返回的日期集合
        List<TimeVo> list=new ArrayList<>();
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Date start = dateFormat.parse(startTime);
            Date end = dateFormat.parse(endTime);
            Calendar tempStart = Calendar.getInstance();
            tempStart.setTime(start);
            Calendar tempEnd = Calendar.getInstance();
            tempEnd.setTime(end);
            getNextDaysDay(tempStart,tempEnd,num,list);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return list;
    }
   public static void getNextDaysDay(Calendar start,Calendar end,int num,List<TimeVo> list){
        Date startTime = start.getTime();
        start.add(Calendar.DATE, num-1);
        Date startTime1 = start.getTime();
        if (start.before(end)){
            TimeVo timeVo=new TimeVo();
            timeVo.setStart(startTime);
            timeVo.setEnd(startTime1);
            start.add(Calendar.DATE, 1);
            start.getTime();
            list.add(timeVo);
            getNextDaysDay(start,end,num,list);
        }else {
            TimeVo timeVo=new TimeVo();
            timeVo.setStart(startTime);
            timeVo.setEnd(end.getTime());
            list.add(timeVo);
            return ;
        }
    }

    public static List<TimeVo> getMonths(int num,String startTime, String endTime) {
        // 返回的日期集合
        List<TimeVo> list=new ArrayList<>();
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Date start = dateFormat.parse(startTime);
            Date end = dateFormat.parse(endTime);
            Calendar tempStart = Calendar.getInstance();
            tempStart.setTime(start);
            Calendar tempEnd = Calendar.getInstance();
            tempEnd.setTime(end);
            getNextMonthDay(tempStart,tempEnd,num,list);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return list;
    }

    public static void getNextMonthDay(Calendar start,Calendar end,int num,List<TimeVo> list){
        Date startTime = start.getTime();
        start.add(Calendar.MONTH, num);
        start.add(Calendar.DATE, -1);
        Date startTime1 = start.getTime();
        if (start.before(end)){
            TimeVo timeVo=new TimeVo();
            timeVo.setStart(startTime);
            timeVo.setEnd(startTime1);
            start.add(Calendar.DATE, 1);
            start.getTime();
            list.add(timeVo);
            getNextMonthDay(start,end,num,list);
        }else {
            TimeVo timeVo=new TimeVo();
            timeVo.setStart(startTime);
            timeVo.setEnd(end.getTime());
            list.add(timeVo);
            return ;
        }
    }

    public static List<TimeVo> getYears(int num,String startTime, String endTime) {
        // 返回的日期集合
        List<TimeVo> list=new ArrayList<>();
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Date start = dateFormat.parse(startTime);
            Date end = dateFormat.parse(endTime);
            Calendar tempStart = Calendar.getInstance();
            tempStart.setTime(start);
            Calendar tempEnd = Calendar.getInstance();
            tempEnd.setTime(end);
            getNextYearsDay(tempStart,tempEnd,num,list);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return list;
    }

    static void getNextYearsDay(Calendar start,Calendar end,int num,List<TimeVo> list){
        Date startTime = start.getTime();
        start.add(Calendar.YEAR, num);
        start.add(Calendar.DATE, -1);
        Date startTime1 = start.getTime();
        if (start.before(end)){
            TimeVo timeVo=new TimeVo();
            timeVo.setStart(startTime);
            timeVo.setEnd(startTime1);
            start.add(Calendar.DATE, 1);
            start.getTime();
            list.add(timeVo);
            getNextYearsDay(start,end,num,list);
        }else {
            TimeVo timeVo=new TimeVo();
            timeVo.setStart(startTime);
            timeVo.setEnd(end.getTime());
            list.add(timeVo);
            return ;
        }
    }


    private static BigDecimal getBigDecimalByMonths(int calculateStyle, int receiptFu, BigDecimal rent,String startTime,String endTime) {
        List<TimeVo> months = getMonths(1, startTime,endTime);
        int size = months.size();
        int lastMonth=months.size()-1;
        TimeVo timeVo = months.get(lastMonth);
        DayCompare dayCompare = dayComparePrecise(timeVo.getStart(), timeVo.getEnd());
        //正好一个账单周期
        if (size==receiptFu){
            int ysall = dayCompare.getMonth();
            //判断最后一个月是否满足一个月
            if (ysall==1){
                //足月
                BigDecimal multiply = DecimalUtils.multiple(rent, receiptFu);
                return multiply;
            }else {
                int mothDays=30;
                if (calculateStyle!=0){
                    Date start = timeVo.getStart();
                    mothDays = com.anti.commom.core.utils.DateUtil.getCurrentMonthDayNum(start);
                }
                BigDecimal multiples = DecimalUtils.multiple(rent,(size-1));
                BigDecimal divide = DecimalUtils.divide(rent,new BigDecimal(mothDays));
                BigDecimal multiple = DecimalUtils.multiple(divide, dayCompare.getDay());
                BigDecimal add = DecimalUtils.add(multiples, multiple);
                return add;
            }
        }else {
            BigDecimal multiple = DecimalUtils.multiple(rent,(size-1));
            //不足一个账单周期
            int mothDays=30;
            if (calculateStyle!=0){
                Date start = timeVo.getStart();
                mothDays = com.anti.commom.core.utils.DateUtil.getCurrentMonthDayNum(start);
            }
            BigDecimal divide = DecimalUtils.divide(rent,new BigDecimal(mothDays));
            BigDecimal multiply = DecimalUtils.multiply(divide, new BigDecimal(dayCompare.getDay()));
            BigDecimal add = DecimalUtils.add(multiply, multiple);
            return add;
        }
    }
    /**
     * 计算2个日期之间相差的  相差多少年月日
     * @param fromDate
     * @param toDate
     * @return
     */
    public static DayCompare dayComparePrecise(Date fromDate,Date toDate){
        //////////////////////////////
        int betweenDay = (int)DateUtil.betweenDay(fromDate, toDate, true)+1;
        int mothDays = com.anti.commom.core.utils.DateUtil.getCurrentMonthDayNum(fromDate);
        int betweenMonth=0;
        if (betweenDay==mothDays){
            betweenMonth=1;
        }
        return DayCompare.builder().day(betweenDay).month(betweenMonth).year(0).build();
    }

    private static BigDecimal getBigDecimalByYears(int calculateStyle, int receiptFu, BigDecimal rent,String startTime,String endTime) {
        //不足一个月按一个月付
        List<TimeVo> months = getMonths(1, startTime,endTime);
        int size = months.size();
        BigDecimal divide = DecimalUtils.divide(rent,new BigDecimal(12));
        BigDecimal multiply = DecimalUtils.multiple(divide, size);
        return multiply;
    }


    public static DayCompare getTimeLength(Date fromDate,Date toDate,int type){
        //////////////////////////////
        HasMonth hasMonth=new HasMonth();
        if (type==1){
            int betweenDay = (int)DateUtil.betweenDay(fromDate, toDate, true)+1;
            return DayCompare.builder().day(betweenDay).month(0).year(0).build();
        }else if (type==2){
            has(DateUtil.format(fromDate,"yyyy-MM-dd"), DateUtil.format(toDate,"yyyy-MM-dd"), hasMonth);
        }else if (type==3) {
            hasYears(DateUtil.format(fromDate,"yyyy-MM-dd"), DateUtil.format(toDate,"yyyy-MM-dd"), hasMonth);
        }
        return DayCompare.builder().day(hasMonth.getDay()).month(hasMonth.getMonth()).year(hasMonth.getYear()).build();
    }


    public static void main(String[] args) {
        DayCompare timeLength = getTimeLength(DateUtil.parse("2021-05-22", "yyyy-MM-dd"), DateUtil.parse("2022-05-21", "yyyy-MM-dd"), 3);
        System.out.println(timeLength);
    }

    public static void has(String startTime, String endTime,HasMonth hasMonth) {
        // 返回的日期集合
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Date start = dateFormat.parse(startTime);
            Date end = dateFormat.parse(endTime);
            Calendar tempStart = Calendar.getInstance();
            tempStart.setTime(start);
            Calendar tempEnd = Calendar.getInstance();
            tempEnd.setTime(end);
            hasNextMonthDay(tempStart,tempEnd,1,hasMonth);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

    public static void hasNextMonthDay(Calendar start,Calendar end,int num,HasMonth hasMonth){
        Date startTime = start.getTime();
        start.add(Calendar.MONTH, num);
        start.add(Calendar.DATE, -1);
        Date startTime1 = start.getTime();
        boolean before = start.before(end);
        if (before){
            TimeVo timeVo=new TimeVo();
            timeVo.setStart(startTime);
            timeVo.setEnd(startTime1);
            start.add(Calendar.DATE, 1);
            start.getTime();
            hasMonth.setMonth(hasMonth.getMonth()+1);
            hasNextMonthDay(start,end,num,hasMonth);
        }else {
            int compare = DateUtil.compare(startTime1, end.getTime());
            if (compare==0){
                hasMonth.setMonth(hasMonth.getMonth()+1);
            }else{
                int betweenDay = (int)DateUtil.betweenDay(startTime, end.getTime(), true)+1;
                hasMonth.setDay(betweenDay);
            }
            return ;
        }
    }



    public static void hasYears(String startTime, String endTime, HasMonth hasMonth) {
        // 返回的日期集合
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Date start = dateFormat.parse(startTime);
            Date end = dateFormat.parse(endTime);
            Calendar tempStart = Calendar.getInstance();
            tempStart.setTime(start);
            Calendar tempEnd = Calendar.getInstance();
            tempEnd.setTime(end);
            hasNextYearsDay(tempStart,tempEnd,1,hasMonth);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

    static void hasNextYearsDay(Calendar start,Calendar end,int num, HasMonth hasMonth){
        Date startTime = start.getTime();
        start.add(Calendar.YEAR, num);
        start.add(Calendar.DATE, -1);
        Date startTime1 = start.getTime();
        if (start.before(end)){
            TimeVo timeVo=new TimeVo();
            timeVo.setStart(startTime);
            timeVo.setEnd(startTime1);
            start.add(Calendar.DATE, 1);
            start.getTime();
            hasMonth.setYear(hasMonth.getYear()+1);
            hasNextYearsDay(start,end,num,hasMonth);
        }else {
            int compare = DateUtil.compare(startTime1, end.getTime());
            if (compare==0){
                hasMonth.setYear(hasMonth.getYear()+1);
            }else{
                has(DateUtil.format(startTime,"yyyy-MM-dd"),DateUtil.format(end.getTime(),"yyyy-MM-dd"), hasMonth);
            }
            return ;
        }
    }

}
